﻿namespace EyeSoft.Accounting.Italian.Istat
{
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.Linq;

	using EyeSoft.Xml.Serialization;

	public class CityRepository
	{
		private static ReadOnlyCollection<Town> townCollection;

		private static ReadOnlyCollection<City> cityCollection;

		private static IEnumerable<Town> TownCollection
		{
			get
			{
				if (townCollection != null)
				{
					return townCollection;
				}

				var serializer = new XmlSerializer<XmlTown>();

				var stream = typeof(XmlTown).ReadResourceText("Internals.Town.xml");

				var list =
					serializer
						.DeserializeCollection(stream)
						.Select(x => new Town(x.Istat, x.Name, x.City, x.Region, x.Prefix, x.Zip, x.Area, x.Population))
						.ToList();

				townCollection = new ReadOnlyCollection<Town>(list);

				return townCollection;
			}
		}

		private static IEnumerable<City> CityCollection
		{
			get
			{
				if (cityCollection != null)
				{
					return cityCollection;
				}

				var serializer = new XmlSerializer<XmlCity>();

				var xml = typeof(Town).ReadResourceText("Internals.City.xml");

				var list =
					serializer
						.DeserializeCollection(xml)
						.Select(x => new City(x.Name, x.Population, x.AreaPercentage, x.AreaTotal, x.Density, x.Towns, x.Province))
						.ToList();

				cityCollection = new ReadOnlyCollection<City>(list);

				return cityCollection;
			}
		}

		public IEnumerable<Town> AllTown()
		{
			return TownCollection;
		}

		public IEnumerable<Town> TownsContains(string partialName)
		{
			return AllTown().Where(town => town.Name.Contains(partialName));
		}

		public IEnumerable<City> AllCity()
		{
			return CityCollection;
		}

		public IEnumerable<City> CitiesContains(string partialName)
		{
			return AllCity().Where(city => city.Name.Contains(partialName));
		}

		public City CityByName(string cityName)
		{
			var cityByName = AllCity().Single(city => city.Name.IgnoreCaseEquals(cityName));

			return cityByName;
		}

		public IEnumerable<Town> TownsInCity(string cityName)
		{
			var city = CityByName(cityName);

			var towns = AllTown().Where(town => town.City.Equals(city.Province));

			return towns;
		}

		public IEnumerable<Town> TownsInCity(string cityName, string townName)
		{
			var towns = TownsInCity(cityName).Where(town => town.Name.IgnoreCaseEquals(townName));

			return towns;
		}

		public IEnumerable<Town> TownsByName(string townName)
		{
			var towns = AllTown().Where(town => town.Name.IgnoreCaseEquals(townName));

			return towns;
		}
	}
}